﻿/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://git.oschina.net/cblock/embedme
 * Copyright 2014~2017 @ ShenZhen ,China
*******************************************************************************/
#ifndef __DEBUG_PRINT_H__
#define __DEBUG_PRINT_H__

/**
 *  \file   Tracer.h   
 *  \brief  调试用跟踪打印类
 *  \note   等级越高越容易打印,高于当前打印等级的都能打印出来
 *          如当前级别为1，则DBG(0)等级的信息不会被打印出来,大
 *          于当前等级的信息都能打印出来.默认为INFO(1)等级.
 */

#include "BaseType.h"
#include "Thread.h"
#include "Mutex.h"
#include "KVProperty.h"
#include <iostream>

#include <typeinfo>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include <sys/time.h>

#if 0 //#ifdef WIN32
#define TRACE_RED(fmt,...)       do{printf("\033[31m\033[1m"fmt"\033[0m",__VA_ARGS__);}while(0)
#endif

/** 颜色打印 */
#define TRACE_RED(fmt,arg...)       do{Tracer::getInstance()->print(TRACE_LEVEL_REL,"\033[31m\033[1m"fmt"\033[0m",##arg);}while(0)
#define TRACE_GREEN(fmt,arg...)     do{Tracer::getInstance()->print(TRACE_LEVEL_REL,"\033[32m\033[1m"fmt"\033[0m",##arg);}while(0)
#define TRACE_YELLOW(fmt,arg...)    do{Tracer::getInstance()->print(TRACE_LEVEL_REL,"\033[33m\033[1m"fmt"\033[0m",##arg);}while(0)
#define TRACE_PINK(fmt,arg...)      do{Tracer::getInstance()->print(TRACE_LEVEL_REL,"\033[35m\033[1m"fmt"\033[0m",##arg);}while(0)
#define TRACE_CYAN(fmt,arg...)      do{Tracer::getInstance()->print(TRACE_LEVEL_REL,"\033[36m\033[1m"fmt"\033[0m",##arg);}while(0)

/** 下面宏实现可以根据信息类型分颜色打印 */
#define TRACE_DBG(fmt,arg...)       do{Tracer::getInstance()->print(TRACE_LEVEL_DBG,"\033[36m\033[1m"fmt"\033[0m",##arg);}while(0)
#define TRACE_REL(fmt,arg...)       do{Tracer::getInstance()->print(TRACE_LEVEL_REL,fmt,##arg);}while(0)
#define TRACE_ERR(fmt,arg...)       do{Tracer::getInstance()->print(TRACE_LEVEL_ERR,"\033[31m\033[1m"fmt"\033[0m",##arg);}while(0)
#define TRACE_WARN(fmt,arg...)      do{Tracer::getInstance()->print(TRACE_LEVEL_WARN,"\033[33m\033[1m"fmt"\033[0m",##arg);}while(0)
#define TRACE_INFO(fmt,arg...)      do{Tracer::getInstance()->print(TRACE_LEVEL_INFO,"\033[32m\033[1m"fmt"\033[0m",##arg);}while(0)

/** 打印16进制字串 */
#define TRACE_HEX(tag,buf,len)      do{Tracer::getInstance()->printHex(TRACE_LEVEL_DBG, tag, buf, len);}while(0)
#define TRACE_TEXT(fmt,arg...)      do{if(Tracer::getInstance()->getLevel()==TRACE_LEVEL_DBG){\
                                       TRACE_CYAN("----------------------------------------\n");\
                                       printf(fmt,arg);\
                                       TRACE_CYAN("\n----------------------------------------\n");\
                                    }}while(0)

/** 下面宏实现可以打印出类名的级别打印(仅在C++类中可使用,需要this指针) */
#define CLASSNAME_STR                   (&(typeid(*this).name()[1]))
#define TRACE_DBG_CLASS(fmt,arg...)     {TRACE_DBG("[%-16s]<DEBUG@%s,L%d>:"fmt,CLASSNAME_STR,__FUNCTION__,__LINE__,##arg);}
#define TRACE_REL_CLASS(fmt,arg...)     {TRACE_REL("[%-16s]"fmt,CLASSNAME_STR,##arg);}
#define TRACE_ERR_CLASS(fmt,arg...)     {TRACE_ERR("[%-16s]<ERROR@%s,L%d>:"fmt,CLASSNAME_STR,__FUNCTION__,__LINE__,##arg);}
#define TRACE_WARN_CLASS(fmt,arg...)    {TRACE_WARN("[%-16s]<WARN @%s,L%d>:"fmt,CLASSNAME_STR,__FUNCTION__,__LINE__,##arg);}
#define TRACE_INFO_CLASS(fmt,arg...)    {TRACE_INFO("[%-16s]<INFO >:"fmt,CLASSNAME_STR,##arg);}

/** 下面的宏用于调试跟踪 */
#define TRACE_IF(condition)         do{if((condition)){TRACE_RED("if(%s)<@%s,L%d>\n",#condition,__FUNCTION__,__LINE__);};}while(0)
#define TRACE_IF_CLASS(condition)   do{if((condition)){TRACE_RED("if(%s)<@%s,L%d>[%s]\n",#condition,__FUNCTION__,__LINE__,CLASSNAME_STR);};}while(0)
#define TRACE_NONE(fmt,arg...)

/** linux标准错误字串 */
#define ERROR_STRING                (strerror(errno))

#define TRACE_LEVEL_REL             4       /**< 用于用户信息的打印 */
#define TRACE_LEVEL_ERR             3       /**< 用于错误信息的打印 */
#define TRACE_LEVEL_WARN            2       /**< 用于警告信息打印 */
#define TRACE_LEVEL_INFO            1       /**< 用于重点提示信息的打印 */
#define TRACE_LEVEL_DBG             0       /**< 用于调试信息的打印 */

/* 配置文件样例(KVProperty属性列表):
 * level = <1>  ;0-Debug,1-Info,2-Warning,3-Error,4-Release
 * 
 */

class Tracer:public Runnable{
public:
    static Tracer* getInstance()
    {
        static Tracer instance;
        return &instance;
    }
    ~Tracer();
    void print(int level,const char* format,...);
    void printMore();
    void printLess();
    void setLevel(int level);
    int getLevel();
    void setEnable(bool enbale);
    char* currentTime();
    void traceTimerBegin();
    void traceTimerEnd();
    void traceTimerDuration();
    void printHex(int level,const char* tag,const char* buf,int len);
    void loadPropertyFile(std::string propFileName,int reloadInterval=1);
private:
    Tracer();
    void run();
private:
    int m_traceLevel;
    bool m_traceEnble;
    struct timeval m_startTime;
    struct timeval m_endTime;
    Thread m_mainThread;
    std::string m_propFileName;
    KVProperty* m_property;
    int m_reloadInterval;
    MutexLock m_propMutex;
};

#endif



